package com.bc.trade.controller;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URLDecoder;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bc.common.CommonEnum.NotifyStatus;
import com.bc.common.CommonEnum.OrderStatus;
import com.bc.common.CommonEnum.Resp;
import com.bc.common.PayType;
import com.bc.common.message.AccountBalanceChangeResp;
import com.bc.trade.channel.ntlmh.NtlmhUtil;
import com.bc.trade.channel.wmyl.WmylChannel;
import com.bc.trade.channel.yufu.YFUtil;
import com.bc.trade.config.R;
import com.bc.trade.config.SystemConfig;
import com.bc.trade.model.Account;
import com.bc.trade.model.Channel;
import com.bc.trade.model.Org;
import com.bc.trade.model.TradeOrder;
import com.bc.trade.noitfy.NotifyReq;
import com.bc.trade.noitfy.NotifyThread;
import com.bc.trade.service.CalcFeeService;
import com.bc.trade.service.VirtualAccountService;
import com.fs.common.extend.FSController;
import com.fs.common.util.FSDate;
import com.fs.common.util.FSHttp;
import com.fs.common.util.FSJson;
import com.fs.common.util.FSLog;
import com.fs.common.util.FSMD5;
import com.fs.common.util.FSString;
import com.github.wxpay.sdk.WXPayUtil;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.yufusoft.payplatform.security.vo.ParamPacket;

public class NotifyController extends FSController {

	private static VirtualAccountService accountService = new VirtualAccountService();
	private final String WMYL_KEY = SystemConfig.channelConfig.get("wmyl_key");
	private final String BUZI_KEY = SystemConfig.channelConfig.get("buzi_key");
	//private final String HICARD_KEY = SystemConfig.channelConfig.get("hicard_key");
	private final String WXGJ_MERCHANT_KEY = SystemConfig.channelConfig.get("wxgj_merchant_ser");
	
	private final String HICARD_FEE = SystemConfig.channelConfig.get("hicard_fee"); //汇卡手续费
	private final String HICARD_MIN_AMT = SystemConfig.channelConfig.get("hicard_min_amt");//汇卡最低手续费
	private final String hicard_that_amt = SystemConfig.channelConfig.get("hicard_that_amt"); //金额手续费低价判断

	public void suningCallback() {
		String queryString = getRequest().getQueryString();
		FSLog.api.info("----------接收苏宁易付宝异步通知 ----------\r\n" + queryString);
		String content = getPara("content");
		FSLog.api.info("content:" + content);
		String sign = getPara("sign");
		FSLog.api.info("sign:" + sign);
		String sign_type = getPara("sign_type");
		FSLog.api.info("sign_type:" + sign_type);
		String vk_version = getPara("vk_version");
		FSLog.api.info("vk_version:" + vk_version);
		if (content == null || content.isEmpty()) {
			FSLog.api.info("没有批次");
			return;
		}

		// 批次
		JSONObject batch = JSONObject.parseObject(content);
		TradeOrder order = TradeOrder.dao.selectByOrderNo(batch.getString("batchNo"));
		if (order == null) {
			FSLog.api.warn("苏宁易付宝异步通知处理，不存在的订单号:" + batch.getString("batchNo"));
			return;
		}
		// 订单状态明确，不重复处理
		if (OrderStatus.Success.getValue().equals(order.getOrderStatus())
				|| OrderStatus.Fail.getValue().equals(order.getOrderStatus())) {
			renderText("true");
			return;
		}
		// 批次状态判断
		if ("04".equals(batch.getString("status"))) {
			order.setOrderStatus(OrderStatus.Fail.getValue());
			order.setRespCode(Resp.Fail.getCode());
			order.setRespMsg("CH(" + batch.getString("errorMsg") + ")");
			order.update();
			renderText("true");
			return;
		}
		// 详情状态
		JSONArray transferOrders = batch.getJSONArray("transferOrders");
		if (transferOrders == null || transferOrders.isEmpty()) {
			FSLog.api.info("批次为空");
			return;
		}
		JSONObject detail = transferOrders.getJSONObject(0);
		String channelOrderNo = detail.getString("id");
		String success = detail.getString("success");
		String payTime = detail.getString("payTime"); // yyyyMMddHHmmss
		payTime = payTime.substring(0, 4) + "-" + payTime.substring(4, 6) + "-" + payTime.substring(6, 8) + " "
				+ payTime.substring(8, 10) + ":" + payTime.substring(10, 12) + ":" + payTime.substring(12, 14);
		String message = detail.getString("errMessage");

		// 成功
		if ("true".equals(success)) {
			// 保存渠道订单号
			order.setOrderStatus(OrderStatus.Success.getValue());
			order.setRespCode(Resp.Success.getCode());
			order.setRespMsg(Resp.Success.getMsg());
			order.setChannelOrderNo(channelOrderNo);
			order.setPayTime(payTime);
			// 更新订单状态和更新虚账余额
			Db.tx(() -> {
				if (StrKit.notBlank(order.getPayTime())) {
					order.setSettleDate(Channel.findSettleDate(order));
				}
				AccountBalanceChangeResp accountResp = accountService.processVirtualAccount(order);
				if (accountResp != null && accountResp.getBalance() != null) {
					order.setBalance(Long.valueOf(accountResp.getBalance()));
				}
				order.update();
				return true;
			});
		}
		// 失败
		else if ("false".equals(success)) {
			order.setOrderStatus(OrderStatus.Fail.getValue());
			order.setRespCode(Resp.Fail.getCode());
			order.setRespMsg("CH(" + message + ")");
			order.update();
		}

		renderText("true");
	}

	/**
	 * 接收kingpay渠道的通知，该渠道“回调请求方式为 HTTP/GET”
	 */
	public void kingpayCallback() {
		String queryString = getRequest().getQueryString();
		FSLog.api.info("----------接收Kingpay异步通知 ----------\r\n" + queryString);
//		getPara("payKey");
//		getPara("productName");
//		getPara("orderPrice");
//		getPara("productType");
//		getPara("orderTime");
//		getPara("trxNo");
//		getPara("remark");
//		getPara("sign");
		String orderNo = getPara("outTradeNo");
		String status = getPara("tradeStatus");
		String payTime = getPara("successTime");// yyyyMMddHHmmss
		payTime = payTime.substring(0, 4) + "-" + payTime.substring(4, 6) + "-" + payTime.substring(6, 8) + " "
				+ payTime.substring(8, 10) + ":" + payTime.substring(10, 12) + ":" + payTime.substring(12, 14);
		TradeOrder order = TradeOrder.dao.selectByOrderNo(orderNo);
		if (order == null) {
			FSLog.api.warn("kingpay异步通知处理，不存在的订单号:" + orderNo);
			return;
		}
		// 订单状态明确，不重复处理
		if (OrderStatus.Success.getValue().equals(order.getOrderStatus())
				|| OrderStatus.Fail.getValue().equals(order.getOrderStatus())) {
			renderText("SUCCESS");
			return;
		}
		// 成功
		if ("SUCCESS".equals(status)) {
			// 保存渠道订单号
			order.setOrderStatus(OrderStatus.Success.getValue());
			order.setRespCode(Resp.Success.getCode());
			order.setRespMsg(Resp.Success.getMsg());
			order.setPayTime(payTime);
			// 更新订单状态和更新虚账余额
			Db.tx(() -> {
				if (StrKit.notBlank(order.getPayTime())) {
					order.setSettleDate(Channel.findSettleDate(order));
				}
				AccountBalanceChangeResp accountResp = accountService.processVirtualAccount(order);
				if (accountResp != null && accountResp.getBalance() != null) {
					order.setBalance(Long.valueOf(accountResp.getBalance()));
				}
				order.update();
				return true;
			});
		}
		// 失败
		else if ("FAILED".equals(status)) {
			order.setOrderStatus(OrderStatus.Fail.getValue());
			order.setRespCode(Resp.Fail.getCode());
			order.update();
		}
		renderText("SUCCESS");
	}

	/**
	 * 接收付保渠道的通知
	 */
	public void ntlmhCallback() {
		String queryString = getRequest().getQueryString();
		FSLog.api.info("----------接收到付宝异步通知 ----------\r\n" + queryString);
		String orderstatus = getPara("orderstatus");
		String ordernumber = getPara("ordernumber");
		String paymoney = getPara("paymoney");
		String sign = getPara("sign");
		// String attach = getPara("attach");
		try {
			StringBuilder sb = new StringBuilder();
			sb.append("partner=").append(SystemConfig.channelConfig.get("NTLMH_merchId")).append("&ordernumber=")
					.append(ordernumber).append("&orderstatus=").append(orderstatus).append("paymoney=")
					.append(paymoney).append(SystemConfig.channelConfig.get("NTLMH_key"));
			String signNow = NtlmhUtil.MD5(sb.toString());
			if (signNow.equalsIgnoreCase(sign)) {
				FSLog.api.warn("验签失败，请求签名=[" + sign + "]，加签结果=[" + signNow + "]");
				return;
			}
			TradeOrder order = TradeOrder.dao.selectByOrderNo(ordernumber);
			if (order == null) {
				FSLog.api.warn("付宝异步通知处理，不存在的订单号:" + ordernumber);
				return;
			}
			// 订单状态明确，不重复处理
			if (OrderStatus.Success.getValue().equals(order.getOrderStatus())
					|| OrderStatus.Fail.getValue().equals(order.getOrderStatus())) {
				renderText("ok");
				return;
			}
			// 成功
			if ("1".equals(orderstatus)) {
				String payTime = FSDate.getDateTime();
				// 保存渠道订单号
				order.setOrderStatus(OrderStatus.Success.getValue());
				order.setRespCode(Resp.Success.getCode());
				order.setRespMsg(Resp.Success.getMsg());
				order.setPayTime(payTime);
				// 更新订单状态和更新虚账余额
				Db.tx(() -> {
					if (StrKit.notBlank(order.getPayTime())) {
						order.setSettleDate(Channel.findSettleDate(order));
					}
					AccountBalanceChangeResp accountResp = accountService.processVirtualAccount(order);
					if (accountResp != null) {
						order.setBalance(Long.valueOf(accountResp.getBalance()));
					}
					order.update();
					return true;
				});
			}
			// 失败
			else {
				order.setOrderStatus(OrderStatus.Fail.getValue());
				order.setRespCode(Resp.Fail.getCode());
				order.update();
			}
			// 通知商户
			NotifyReq notifyReq = new NotifyReq(order);
			NotifyThread.getInstance().addNotifyOrder(notifyReq);
		} catch (Exception e) {
			FSLog.api.error("处理通知异常", e);
		}
		renderText("ok");
	}

	public void kkr() {
		yfNotify("YFKKR");
	}

	public void zz() {
		yfNotify("YFZZ");
	}

	public void jn() {
		yfNotify("YFJN");
	}

	public void yfNotify(String channelCode) {
		String data = getPara("data");
		String enc = getPara("enc");
		String sign = getPara("sign");
		try {
			Map<String, String> notifyData = YFUtil.getCipherInstance(channelCode)
					.unPack(new ParamPacket(data, enc, sign));
			FSLog.api.info("----------YF异步通 ----------\r\n" + notifyData);
			String orderNo = notifyData.get("merchantOrderId");

			// 逐个订单号使用事务处理
			Db.tx(() -> {
				// 行锁取出订单
				TradeOrder order = TradeOrder.dao.selectByOrderNoForUpdate(orderNo);
				if (order == null) {
					System.out.println("订单号不存在orderNo=[" + orderNo + "]");
					return true;
				}
				// 订单状态检测
				if (OrderStatus.Create.getValue().equals(order.getOrderStatus())
						|| OrderStatus.Unknow.getValue().equals(order.getOrderStatus())
						|| OrderStatus.InProcess.getValue().equals(order.getOrderStatus())) {
					FSLog.task.info("处理通知订单：" + order.toString());
					String transStatus = notifyData.get("transStatus");
					if (order.getPayType().equals(PayType.DF_PERSONAL)
							|| order.getPayType().equals(PayType.DF_COMPANY)) {
						if (transStatus.equals("05")) {
							order.setChannelOrderNo(notifyData.get("bpSerialNum"));
							order.setPayTime(FSDate.formatDateTime(notifyData.get("transTime"), "yyyyMMddHHmmss",
									"yyyy-MM-dd HH:mm:ss"));
							order.setRespCode(Resp.Success.getCode());
							order.setRespMsg(Resp.Success.getMsg());
							order.setOrderStatus(OrderStatus.Success.getValue());
						} else {
							order.setRespCode(Resp.Fail.getCode());
							order.setRespMsg("CH" + notifyData.get("respDesc"));
							order.setOrderStatus(OrderStatus.Fail.getValue());
						}
					} else {
						if (transStatus.equals("01")) {
							order.setChannelOrderNo(notifyData.get("bpSerialNum"));
							order.setPayTime(FSDate.formatDateTime(notifyData.get("transTime"), "yyyyMMddHHmmss",
									"yyyy-MM-dd HH:mm:ss"));
							order.setRespCode(Resp.Success.getCode());
							order.setRespMsg(Resp.Success.getMsg());
							order.setOrderStatus(OrderStatus.Success.getValue());
							if (order.getPayType().equals(PayType.REFUND)) {
								TradeOrder oriOrder = TradeOrder.dao.selectByOrderNo(order.getOriginalOrderNo());
								oriOrder.setOrderStatus(OrderStatus.Refund.getValue());
								oriOrder.update();
							}
						} else {
							order.setRespCode(Resp.Fail.getCode());
							order.setRespMsg("CH" + notifyData.get("respDesc"));
							order.setOrderStatus(OrderStatus.Fail.getValue());
						}
					}
					if (StrKit.notBlank(order.getPayTime())) {
						order.setSettleDate(Channel.findSettleDate(order));
					}
					AccountBalanceChangeResp accountResp = accountService.processVirtualAccount(order);
					if (accountResp != null) {
						order.setBalance(Long.valueOf(accountResp.getBalance()));
					}
					order.update();
					// 通知商户
					NotifyThread.getInstance().addNotifyOrder(order);
					return true;
				} else {
					// 状态明确的订单不处理(或已经收到异步通知了)
					return true;
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			renderText("success");
		}
	}

	public void merchReturn() {
		String notifyString = getStringFromRequest();
		System.out.println("测试商户回调->" + notifyString);
		renderText("000000");
	}

	public void merchNotify() {
		String notifyString = getStringFromRequest();
		System.out.println("测试商户回调->" + notifyString);
		renderText("SUCCESS");
	}

	public void aliNotify() {
		try {
			// String callback = getPara("callback");
			String json = getPara("json");
			json = URLDecoder.decode(json, "UTF-8");
			System.out.println("接收到支付宝网页插件通知：" + json);
			TreeMap<String, String> map = FSJson.toTreeMap(json);
			String remark = map.get("remark");
			String aliNo = map.get("aliNo");
			TradeOrder order = TradeOrder.dao.selectByRemark(remark);
			if (order == null) {
				FSLog.api.warn("未找到符合条件的订单，备注=[" + remark + "]，支付宝订单号=[" + aliNo + "]");
				renderText("console.log('[success]" + remark + "@" + aliNo + "');", "text/javascript");
				return;
			}

			String payTime = FSDate.getDateTime();
			// 保存渠道订单号
			order.setOrderStatus(OrderStatus.Success.getValue());
			order.setRespCode(Resp.Success.getCode());
			order.setRespMsg(Resp.Success.getMsg());
			order.setPayTime(payTime);
			// 更新订单状态和更新虚账余额
			Db.tx(() -> {
				if (StrKit.notBlank(order.getPayTime())) {
					order.setSettleDate(Channel.findSettleDate(order));
				}
				AccountBalanceChangeResp accountResp = accountService.processVirtualAccount(order);
				if (accountResp != null) {
					order.setBalance(Long.valueOf(accountResp.getBalance()));
				}
				order.update();
				return true;
			});
			renderText("console.log('[success]" + remark + "@" + aliNo + "');", "text/javascript");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * 万茂运龙交易异步通知
	 */
	public void wmylTradeNotify() {
		String parameterString = "";
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(getRequest().getInputStream(), "UTF-8"));
			StringBuffer buffer = new StringBuffer();
			String string;
			while ((string = reader.readLine()) != null) {
				buffer.append(string);
			}
			parameterString = URLDecoder.decode(buffer.toString(), "UTF-8");

		} catch (Exception e) {
			e.printStackTrace();
		}
		FSLog.api.info("收到WMYL交易异步通知-> \r\n" + parameterString);
		Map<String, String> reqMap = FSString.convertUrlParameterToMap(parameterString);
		String sign = reqMap.get("sign");
		reqMap.remove("sign");
		TreeMap<String, String> map = new TreeMap<String, String>();
		map.putAll(reqMap);
		String signStr = WmylChannel.postString(map);
		String mySign = FSMD5.codeFor(signStr + WMYL_KEY).toUpperCase();
		if (!mySign.equals(sign)) {
			renderText("signfail");
			return;
		}

		try {
			String orderNo = map.get("orderNo");

			// 逐个订单号使用事务处理
			Db.tx(() -> {
				// 行锁取出订单
				TradeOrder order = TradeOrder.dao.selectByOrderNoForUpdate(orderNo);
				if (order == null) {
					FSLog.task.info("订单号不存在orderNo=[" + orderNo + "]");
					return true;
				}
				// 订单状态检测
				if (OrderStatus.Create.getValue().equals(order.getOrderStatus())
						|| OrderStatus.Unknow.getValue().equals(order.getOrderStatus())
						|| OrderStatus.InProcess.getValue().equals(order.getOrderStatus())) {
					FSLog.task.info("处理通知订单：" + order.toString());
					order.setChannelOrderNo(map.get("acqRefNo"));
					order.setPayTime(FSDate.getDateTime());
					order.setRespCode(Resp.Success.getCode());
					order.setRespMsg(Resp.Success.getMsg());
					order.setOrderStatus(OrderStatus.Success.getValue());
					order.setSettleDate(Channel.findSettleDate(order));
					AccountBalanceChangeResp accountResp = accountService.processVirtualAccount(order);
					if (accountResp != null) {
						order.setBalance(Long.valueOf(accountResp.getBalance()));
					}
					order.update();
					// 通知商户
					NotifyThread.getInstance().addNotifyOrder(order);
					return true;
				} else {
					// 状态明确的订单不处理(或已经收到异步通知了)
					return true;
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			renderText("success");
		}
	}

	/**
	 * 万茂运龙代付异步通知
	 */
	public void wmylPayNotify() {
		String parameterString = "";
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(getRequest().getInputStream(), "UTF-8"));
			StringBuffer buffer = new StringBuffer();
			String string;
			while ((string = reader.readLine()) != null) {
				buffer.append(string);
			}
			parameterString = URLDecoder.decode(buffer.toString(), "UTF-8");

		} catch (Exception e) {
			e.printStackTrace();
		}
		FSLog.api.info("收到WMYL交易异步通知-> \r\n" + parameterString);
		Map<String, String> reqMap = FSString.convertUrlParameterToMap(parameterString);
		String sign = reqMap.get("sign");
		reqMap.remove("sign");
		TreeMap<String, String> map = new TreeMap<String, String>();
		map.putAll(reqMap);
		String signStr = WmylChannel.postString(map);
		String mySign = FSMD5.codeFor(signStr + WMYL_KEY).toUpperCase();
		if (!mySign.equals(sign)) {
			renderText("signfail");
			return;
		}

		try {
			String orderNo = map.get("payNo");

			// 逐个订单号使用事务处理
			Db.tx(() -> {
				// 行锁取出订单
				TradeOrder order = TradeOrder.dao.selectByOrderNoForUpdate(orderNo);
				if (order == null) {
					FSLog.task.info("订单号不存在orderNo=[" + orderNo + "]");
					return true;
				}
				// 订单状态检测
				if (OrderStatus.Create.getValue().equals(order.getOrderStatus())
						|| OrderStatus.Unknow.getValue().equals(order.getOrderStatus())
						|| OrderStatus.InProcess.getValue().equals(order.getOrderStatus())) {
					FSLog.task.info("处理通知订单：" + order.toString());
					order.setChannelOrderNo(map.get("orderNo"));
					order.setPayTime(FSDate.getDateTime());
					order.setRespCode(Resp.Success.getCode());
					order.setRespMsg(Resp.Success.getMsg());
					order.setOrderStatus(OrderStatus.Success.getValue());
					order.setSettleDate(Channel.findSettleDate(order));
					AccountBalanceChangeResp accountResp = accountService.processVirtualAccount(order);
					if (accountResp != null) {
						order.setBalance(Long.valueOf(accountResp.getBalance()));
					}
					order.update();
					// 通知商户
					NotifyThread.getInstance().addNotifyOrder(order);
					return true;
				} else {
					// 状态明确的订单不处理(或已经收到异步通知了)
					return true;
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			renderText("success");
		}
	}

	/**
	 * 步子支付异步通知
	 */
	public void buziTradeNotify() {
		String parameterString = "";
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(getRequest().getInputStream(), "UTF-8"));
			StringBuffer buffer = new StringBuffer();
			String string;
			while ((string = reader.readLine()) != null) {
				buffer.append(string);
			}
			parameterString = URLDecoder.decode(buffer.toString(), "UTF-8");

		} catch (Exception e) {
			e.printStackTrace();
		}
		FSLog.api.info("收到步子交易异步通知-> \r\n" + parameterString);
		Map<String, String> reqMap = FSString.convertUrlParameterToMap(parameterString);
		String sign = reqMap.get("sign");
		reqMap.remove("sign");
		TreeMap<String, String> map = new TreeMap<String, String>();
		map.putAll(reqMap);
		String mySign = FSMD5.sortSign(map, "key=" + BUZI_KEY);
		if (!mySign.equals(sign)) {
			renderText("signfail");
			return;
		}

		try {
			String orderNo = map.get("orderid");

			// 逐个订单号使用事务处理
			Db.tx(() -> {
				// 行锁取出订单
				TradeOrder order = TradeOrder.dao.selectByOrderNoForUpdate(orderNo);
				if (order == null) {
					FSLog.task.info("订单号不存在orderNo=[" + orderNo + "]");
					return true;
				}
				// 订单状态检测
				if (OrderStatus.Create.getValue().equals(order.getOrderStatus())
						|| OrderStatus.Unknow.getValue().equals(order.getOrderStatus())
						|| OrderStatus.InProcess.getValue().equals(order.getOrderStatus())) {
					FSLog.task.info("处理通知订单：" + order.toString());
					order.setChannelOrderNo(map.get("orderNo"));
					order.setPayTime(FSDate.getDateTime());
					order.setRespCode(Resp.Success.getCode());
					order.setRespMsg(Resp.Success.getMsg());
					order.setOrderStatus(OrderStatus.Success.getValue());
					order.setSettleDate(Channel.findSettleDate(order));
					AccountBalanceChangeResp accountResp = accountService.processVirtualAccount(order);
					if (accountResp != null) {
						order.setBalance(Long.valueOf(accountResp.getBalance()));
					}
					order.update();
					// 通知商户
					NotifyThread.getInstance().addNotifyOrder(order);
					return true;
				} else {
					// 状态明确的订单不处理(或已经收到异步通知了)
					return true;
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			renderText("OK");
		}
	}
	
	//微信国际退款的回调
	public void wxgjRefNotify() throws Exception {
		String parameterString = "";
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(getRequest().getInputStream(), "UTF-8"));
			StringBuffer buffer = new StringBuffer();
			String string;
			while ((string = reader.readLine()) != null) {
				buffer.append(string);
			}
			parameterString = URLDecoder.decode(buffer.toString(), "UTF-8");

		} catch (Exception e) {
			e.printStackTrace();
		}
		FSLog.api.info("微信国际退款-----收到微信国际交易异步通知-> \r\n" + parameterString);
		
		Map<String, String> map = WXPayUtil.xmlToMap(parameterString);
		FSLog.api.info("微信国际退款--------收到微信国际交易异步通知Map-> \r\n" + map.toString());
		String sign = map.get("sign");
		String mySign = WXPayUtil.generateSignature(map, WXGJ_MERCHANT_KEY);
		if (!mySign.equals(sign)) {
			renderText("signfail");
			return;
		}
		String return_code = map.get("return_code");
		String result_code = map.get("result_code");
		String time_end = map.get("time_end");
		String transaction_id = map.get("transaction_id");
		String out_trade_no = map.get("out_trade_no");
		String total_fee = map.get("total_fee");
		String err_code = map.get("err_code");
		String err_code_des = map.get("err_code_des");
		
		if(!"SUCCESS".equals(result_code) || !"SUCCESS".equals(return_code) ) {
			return ;
		}
		
		Db.tx(() -> {
			TradeOrder order = TradeOrder.dao.selectByOrderNoForUpdate(out_trade_no);
			if (order == null) {
				FSLog.task.info("订单号不存在orderNo=[" + out_trade_no + "]");
				return true;
			}
			
			//order.setAmount(order.getTotalFee() + );
			//order.update();//退款成功
//			if(order.getNotifyUrl()!=null && 0<order.getNotifyUrl().length()) {
//				NotifyThread.getInstance().addNotifyOrder(order);
//			}
			
			return true;
		});
		
		String resXml = "<xml>" + 
				"" + 
				"<return_code><![CDATA[SUCCESS]]></return_code>" + 
				"<return_msg><![CDATA[OK]]></return_msg>" + 
				"</xml>";
		renderText(resXml);
		
	}

	// 微信国际的支付回调
	public void wxgjpayNotify() {
		String parameterString = "";
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(getRequest().getInputStream(), "UTF-8"));
			StringBuffer buffer = new StringBuffer();
			String string;
			while ((string = reader.readLine()) != null) {
				buffer.append(string);
			}
			parameterString = URLDecoder.decode(buffer.toString(), "UTF-8");

		} catch (Exception e) {
			e.printStackTrace();
		}
		FSLog.api.info("收到微信国际交易异步通知-> \r\n" + parameterString);

		try {
			Map<String, String> map = WXPayUtil.xmlToMap(parameterString);
			
			FSLog.api.info("收到微信国际交易异步通知Map-> \r\n" + map.toString());

			String sign = map.get("sign");
			String mySign = WXPayUtil.generateSignature(map, WXGJ_MERCHANT_KEY);
			if (!mySign.equals(sign)) {
				renderText("signfail");
				return;
			}
			String return_code = map.get("return_code");
			String result_code = map.get("result_code");
			String time_end = map.get("time_end");
			String transaction_id = map.get("transaction_id");
			String out_trade_no = map.get("out_trade_no");
			String total_fee = map.get("total_fee");
			String err_code = map.get("err_code");
			String err_code_des = map.get("err_code_des");
			
			if(!"SUCCESS".equals(result_code) || !"SUCCESS".equals(return_code) ) {
				return ;
			}
			
			String resXml = "<xml>" + 
					"" + 
					"<return_code><![CDATA[SUCCESS]]></return_code>" + 
					"<return_msg><![CDATA[OK]]></return_msg>" + 
					"</xml>";

			// 逐个订单号使用事务处理
			Db.tx(() -> {
				// 行锁取出订单
				TradeOrder order = TradeOrder.dao.selectByOrderNoForUpdate(out_trade_no);
				if (order == null) {
					FSLog.task.info("订单号不存在orderNo=[" + out_trade_no + "]");
					return true;
				}
				
				if(order.getAmount() != Integer.parseInt(total_fee)) {
					FSLog.task.info("微信国际, 订单orderNo=[" + out_trade_no + "]" + "金额不符合!");
					return true;
				}
				//已经查询成功了,并且没有进入虚账,那么进入虚账和 异步通知商户
				if(OrderStatus.Success.getValue().equals(order.getOrderStatus())
						&& !order.getIsInVirtualAccount()){
					order.setRespCode(Resp.Success.getCode());
					order.setRespMsg(Resp.Success.getMsg());
					order.setOrderStatus(OrderStatus.Success.getValue());
					order.setSettleDate(Channel.findSettleDate(order));
					
					order.setIsD0(true);// 不可提现
					AccountBalanceChangeResp accountResp = accountService.processVirtualAccount(order);
					if (accountResp != null) {
						order.setBalance(Long.valueOf(accountResp.getBalance()));
						order.setIsInVirtualAccount(true);
						order.update();
					}
					
					// 通知商户
					if (!"http://www.soeasy-tech.com".equals(order.getNotifyUrl())) {
						NotifyThread.getInstance().addNotifyOrder(order);
					}
					
					// 状态明确的订单
					renderText(resXml);
					return true;
				}

				// 订单状态检测
				if ((OrderStatus.Create.getValue().equals(order.getOrderStatus())
						|| OrderStatus.Unknow.getValue().equals(order.getOrderStatus())
						|| OrderStatus.InProcess.getValue().equals(order.getOrderStatus()))) {
					FSLog.task.info("微信国际处理通知订单：" + order.toString());
					order.setChannelOrderNo(transaction_id);
					String payTime = FSDate.formatDateTime(time_end, "yyyyMMddHHmmss", "yyyy-MM-dd HH:mm:ss");
					order.setPayTime(payTime);
					if ("SUCCESS".equals(result_code) && "SUCCESS".equals(return_code)) {
						order.setRespCode(Resp.Success.getCode());
						order.setRespMsg(Resp.Success.getMsg());
						order.setOrderStatus(OrderStatus.Success.getValue());
						order.setSettleDate(Channel.findSettleDate(order));
						
						order.setIsD0(true);// 不可提现
						AccountBalanceChangeResp accountResp = accountService.processVirtualAccount(order);
						if (accountResp != null) {
							order.setBalance(Long.valueOf(accountResp.getBalance()));
							order.setIsInVirtualAccount(true);
						}
						
					} else {
						order.setRespCode(Resp.Fail.getCode());
						order.setRespMsg(err_code + "-" + err_code_des);
						order.setOrderStatus(OrderStatus.Fail.getValue());
					}
					FSLog.task.info("处理完成订单：" + order.toString());
					order.update();
//					// 通知商户
					if (!"http://www.soeasy-tech.com".equals(order.getNotifyUrl())) {
						NotifyThread.getInstance().addNotifyOrder(order);
					}
					
//					if(order.getReturnUrl()!=null && 0 < order.getReturnUrl().length()) {
//						TradeOrder myOrder = new TradeOrder();
//						NotifyThread.getInstance().addNotifyOrder(myOrder);
//					}
					//调转到成功页面!
					renderText(resXml);
					return true;

				} else {
					// 状态明确的订单不处理(或已经收到异步通知了)
					renderText(resXml);
					return true;
				}
			});

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public void hicardNotify() {
		String parameterString = "";
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(getRequest().getInputStream(), "UTF-8"));
			StringBuffer buffer = new StringBuffer();
			String string;
			while ((string = reader.readLine()) != null) {
				buffer.append(string);
			}
			parameterString = URLDecoder.decode(buffer.toString(), "UTF-8");

		} catch (Exception e) {
			e.printStackTrace();
		}
		FSLog.api.info("收到汇卡交易异步通知-> \r\n" + parameterString);

		Map<String, String> map = FSJson.toMap(parameterString);
		String sign = map.get("sign");
		String hicardMerchNo = map.get("hicardMerchNo");
		
		String hkKEY = Account.dao.findHkKey(hicardMerchNo);
		
		String mySign = FSMD5.sortSign(map, hkKEY).toLowerCase();
		if (!mySign.equals(sign)) {
			renderText("signfail");
			return;
		}

		try {
			String respCode = map.get("respCode");
			String hicardOrderNo = map.get("hicardOrderNo");
			String orderNo = map.get("merchOrderNo");
			String payTime = map.get("payTime");

			// 逐个订单号使用事务处理
			Db.tx(() -> {
				// 行锁取出订单
				TradeOrder order = TradeOrder.dao.selectByOrderNoForUpdate(orderNo);
				if (order == null) {
					FSLog.task.info("订单号不存在orderNo=[" + orderNo + "]");
					return true;
				}

				// 订单状态检测
				if ((OrderStatus.Create.getValue().equals(order.getOrderStatus())
						|| OrderStatus.Unknow.getValue().equals(order.getOrderStatus())
						|| OrderStatus.InProcess.getValue().equals(order.getOrderStatus()))) {
					FSLog.task.info("处理通知订单：" + order.toString());
					order.setChannelOrderNo(hicardOrderNo);
					order.setPayTime(payTime);
					if ("00".equals(respCode)) {
						order.setRespCode(Resp.Success.getCode());
						order.setRespMsg(Resp.Success.getMsg());
						order.setOrderStatus(OrderStatus.Success.getValue());
						order.setSettleDate(Channel.findSettleDate(order));

						if (StrKit.notBlank(payTime) && payTime.length() == 19) {
							String time = payTime.substring(11, 19);
							if (time.compareTo("09:00:00") >= 0 && time.compareTo("21:30:00") <= 0) {
								order.setIsD0(false);// 入到T1余额
							} else {
								order.setIsD0(true);// 入到D0余额
							}
						}

						AccountBalanceChangeResp accountResp = accountService.processVirtualAccount(order);
						if (accountResp != null) {
							order.setBalance(Long.valueOf(accountResp.getBalance()));
							order.setIsInVirtualAccount(true);

							// 再入到汇卡商户号对应的虚账上
							CalcFeeService calc = new CalcFeeService();
							Integer channelFee = calc.calcResult(order.getAmount(), HICARD_FEE, 0, 0);
							if(order.getAmount() < Integer.parseInt(hicard_that_amt)) {
								channelFee = Integer.parseInt(HICARD_MIN_AMT);
							}
							AccountBalanceChangeResp hicardAccountResp = accountService.addMoney(order.getIsD0(),
									"hicard", order.getOtherMerchCode(), order.getAmount() - channelFee);
							if (hicardAccountResp != null) {
								FSLog.task.info("订单号" + order.getOrderNo() + "入汇卡商户号对应的虚账成功。");
							}

						}
					} else {
						order.setRespCode(Resp.Fail.getCode());
						order.setRespMsg(respCode + "-" + map.get("respMsg"));
						order.setOrderStatus(OrderStatus.Fail.getValue());
					}
					FSLog.task.info("处理完成订单：" + order.toString());
					order.update();
					// 通知商户
					NotifyThread.getInstance().addNotifyOrder(order);
					return true;

				} else {
					// 状态明确的订单不处理(或已经收到异步通知了)
					return true;
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			renderText("SUCCESS");
		}
	}

	/**
	 * 后台主动推送
	 */
	public void adminPush() {
		String id = getStringFromRequest();
		TradeOrder order = TradeOrder.dao.findById(id);
		NotifyReq req = new NotifyReq(order);
		req.setVersion("V1.0");
		req.setSign(FSMD5.sortSign(req, Org.dao.selectSafeKey(order.getOrgCode())));
		try {
			String result = FSHttp.postJson(order.getNotifyUrl(), FSJson.toString(req));
			if (("SUCCESS").equals(result)) {
				TradeOrder.dao.updateNotifyStatus(order.getOrderNo(), NotifyStatus.Success.getValue());
			}
			renderText(result);
		} catch (Exception e) {
			e.printStackTrace();
			renderText("交易系统推送异常");
			TradeOrder.dao.updateNotifyStatus(order.getOrderNo(), NotifyStatus.Fail.getValue());
		}
	}

	public void testPush() {
		String id = getStringFromRequest();
		TradeOrder order = TradeOrder.dao.findById(id);
		NotifyThread.getInstance().addNotifyOrder(order);
		renderText("success");
	}

	public void loadHicardMerch() {
		List<Account> hicardMerchantList = Account.dao.selectHicardAccountNo();
		FSLog.api.info("loadHicardMerch: 汇卡商户号:有效的汇卡商户号的个数:" + hicardMerchantList);
		renderText("有效的汇卡商户号的个数:" + hicardMerchantList.size());
	}

}
